home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / mint / netlib / lib / rcomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  8.6 KB  |  359 lines

  1. /*
  2.  * Adopted to Mint-Net 1994, Kay Roemer.
  3.  */
  4.  
  5. /*
  6.  * Copyright (c) 1985 Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37.  
  38. #if defined(LIBC_SCCS) && !defined(lint)
  39. static char sccsid[] = "@(#)res_comp.c    6.22 (Berkeley) 3/19/91";
  40. #endif /* LIBC_SCCS and not lint */
  41.  
  42. #include "socklib.h"
  43. #include <sys/param.h>
  44. #include <arpa/nameser.h>
  45. #include <netinet/in.h>
  46. #include <resolv.h>
  47. #include <stdio.h>
  48.  
  49. static dn_find();
  50.  
  51. /*
  52.  * Expand compressed domain name 'comp_dn' to full domain name.
  53.  * 'msg' is a pointer to the begining of the message,
  54.  * 'eomorig' points to the first location after the message,
  55.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  56.  * Return size of compressed name or -1 if there was an error.
  57.  */
  58. int
  59. dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  60.     u_char *msg, *eomorig, *comp_dn;
  61.     u_char *exp_dn;
  62.     int length;
  63. {
  64.     register u_char *cp, *dn;
  65.     register int n, c;
  66.     u_char *eom;
  67.     int len = -1, checked = 0;
  68.  
  69.     dn = exp_dn;
  70.     cp = (u_char *)comp_dn;
  71.     eom = exp_dn + length;
  72.     /*
  73.      * fetch next label in domain name
  74.      */
  75.     while (n = *cp++) {
  76.         /*
  77.          * Check for indirection
  78.          */
  79.         switch (n & INDIR_MASK) {
  80.         case 0:
  81.             if (dn != exp_dn) {
  82.                 if (dn >= eom)
  83.                     return (-1);
  84.                 *dn++ = '.';
  85.             }
  86.             if (dn+n >= eom)
  87.                 return (-1);
  88.             checked += n + 1;
  89.             while (--n >= 0) {
  90.                 if ((c = *cp++) == '.') {
  91.                     if (dn + n + 2 >= eom)
  92.                         return (-1);
  93.                     *dn++ = '\\';
  94.                 }
  95.                 *dn++ = c;
  96.                 if (cp >= eomorig)    /* out of range */
  97.                     return(-1);
  98.             }
  99.             break;
  100.  
  101.         case INDIR_MASK:
  102.             if (len < 0)
  103.                 len = cp - comp_dn + 1;
  104.             cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  105.             if (cp < msg || cp >= eomorig)    /* out of range */
  106.                 return(-1);
  107.             checked += 2;
  108.             /*
  109.              * Check for loops in the compressed name;
  110.              * if we've looked at the whole message,
  111.              * there must be a loop.
  112.              */
  113.             if (checked >= eomorig - msg)
  114.                 return (-1);
  115.             break;
  116.  
  117.         default:
  118.             return (-1);            /* flag error */
  119.         }
  120.     }
  121.     *dn = '\0';
  122.     if (len < 0)
  123.         len = cp - comp_dn;
  124.     return (len);
  125. }
  126.  
  127. /*
  128.  * Compress domain name 'exp_dn' into 'comp_dn'.
  129.  * Return the size of the compressed name or -1.
  130.  * 'length' is the size of the array pointed to by 'comp_dn'.
  131.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  132.  * is a pointer to the beginning of the message. The list ends with NULL.
  133.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  134.  * by 'dnptrs'. Side effect is to update the list of pointers for
  135.  * labels inserted into the message as we compress the name.
  136.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  137.  * is NULL, we don't update the list.
  138.  */
  139. int
  140. dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  141.     u_char *exp_dn;
  142.     u_char *comp_dn, **dnptrs, **lastdnptr;
  143.     int length;
  144. {
  145.     register u_char *cp, *dn;
  146.     register int c, l;
  147.     u_char **cpp, **lpp, *sp, *eob;
  148.     u_char *msg;
  149.  
  150.     dn = (u_char *)exp_dn;
  151.     cp = comp_dn;
  152.     eob = cp + length;
  153.     if (dnptrs != NULL) {
  154.         if ((msg = *dnptrs++) != NULL) {
  155.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  156.                 ;
  157.             lpp = cpp;    /* end of list to search */
  158.         }
  159.     } else
  160.         msg = NULL;
  161.     for (c = *dn++; c != '\0'; ) {
  162.         /* look to see if we can use pointers */
  163.         if (msg != NULL) {
  164.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  165.                 if (cp+1 >= eob)
  166.                     return (-1);
  167.                 *cp++ = (l >> 8) | INDIR_MASK;
  168.                 *cp++ = l % 256;
  169.                 return (cp - comp_dn);
  170.             }
  171.             /* not found, save it */
  172.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  173.                 *cpp++ = cp;
  174.                 *cpp = NULL;
  175.             }
  176.         }
  177.         sp = cp++;    /* save ptr to length byte */
  178.         do {
  179.             if (c == '.') {
  180.                 c = *dn++;
  181.                 break;
  182.             }
  183.             if (c == '\\') {
  184.                 if ((c = *dn++) == '\0')
  185.                     break;
  186.             }
  187.             if (cp >= eob) {
  188.                 if (msg != NULL)
  189.                     *lpp = NULL;
  190.                 return (-1);
  191.             }
  192.             *cp++ = c;
  193.         } while ((c = *dn++) != '\0');
  194.         /* catch trailing '.'s but not '..' */
  195.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  196.             cp--;
  197.             break;
  198.         }
  199.         if (l <= 0 || l > MAXLABEL) {
  200.             if (msg != NULL)
  201.                 *lpp = NULL;
  202.             return (-1);
  203.         }
  204.         *sp = l;
  205.     }
  206.     if (cp >= eob) {
  207.         if (msg != NULL)
  208.             *lpp = NULL;
  209.         return (-1);
  210.     }
  211.     *cp++ = '\0';
  212.     return (cp - comp_dn);
  213. }
  214.  
  215. /*
  216.  * Skip over a compressed domain name. Return the size or -1.
  217.  */
  218. int
  219. __dn_skipname(comp_dn, eom)
  220.     u_char *comp_dn, *eom;
  221. {
  222.     register u_char *cp;
  223.     register int n;
  224.  
  225.     cp = (u_char *)comp_dn;
  226.     while (cp < eom && (n = *cp++)) {
  227.         /*
  228.          * check for indirection
  229.          */
  230.         switch (n & INDIR_MASK) {
  231.         case 0:        /* normal case, n == len */
  232.             cp += n;
  233.             continue;
  234.         default:    /* illegal type */
  235.             return (-1);
  236.         case INDIR_MASK:    /* indirection */
  237.             cp++;
  238.         }
  239.         break;
  240.     }
  241.     return (cp - comp_dn);
  242. }
  243.  
  244. /*
  245.  * Search for expanded name from a list of previously compressed names.
  246.  * Return the offset from msg if found or -1.
  247.  * dnptrs is the pointer to the first name on the list,
  248.  * not the pointer to the start of the message.
  249.  */
  250. static int
  251. dn_find(exp_dn, msg, dnptrs, lastdnptr)
  252.     u_char *exp_dn, *msg;
  253.     u_char **dnptrs, **lastdnptr;
  254. {
  255.     register u_char *dn, *cp, **cpp;
  256.     register int n;
  257.     u_char *sp;
  258.  
  259.     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  260.         dn = exp_dn;
  261.         sp = cp = *cpp;
  262.         while (n = *cp++) {
  263.             /*
  264.              * check for indirection
  265.              */
  266.             switch (n & INDIR_MASK) {
  267.             case 0:        /* normal case, n == len */
  268.                 while (--n >= 0) {
  269.                     if (*dn == '.')
  270.                         goto next;
  271.                     if (*dn == '\\')
  272.                         dn++;
  273.                     if (*dn++ != *cp++)
  274.                         goto next;
  275.                 }
  276.                 if ((n = *dn++) == '\0' && *cp == '\0')
  277.                     return (sp - msg);
  278.                 if (n == '.')
  279.                     continue;
  280.                 goto next;
  281.  
  282.             default:    /* illegal type */
  283.                 return (-1);
  284.  
  285.             case INDIR_MASK:    /* indirection */
  286.                 cp = msg + (((n & 0x3f) << 8) | *cp);
  287.             }
  288.         }
  289.         if (*dn == '\0')
  290.             return (sp - msg);
  291.     next:    ;
  292.     }
  293.     return (-1);
  294. }
  295.  
  296. /*
  297.  * Routines to insert/extract short/long's. Must account for byte
  298.  * order and non-alignment problems. This code at least has the
  299.  * advantage of being portable.
  300.  *
  301.  * used by sendmail.
  302.  */
  303.  
  304. u_short
  305. _getshort(msgp)
  306.     u_char *msgp;
  307. {
  308.     register u_char *p = (u_char *) msgp;
  309. #ifdef vax
  310.     /*
  311.      * vax compiler doesn't put shorts in registers
  312.      */
  313.     register u_long u;
  314. #else
  315.     register u_short u;
  316. #endif
  317.  
  318.     u = *p++ << 8;
  319.     return ((u_short)(u | *p));
  320. }
  321.  
  322. u_long
  323. _getlong(msgp)
  324.     u_char *msgp;
  325. {
  326.     register u_char *p = (u_char *) msgp;
  327.     register u_long u;
  328.  
  329.     u = *p++; u <<= 8;
  330.     u |= *p++; u <<= 8;
  331.     u |= *p++; u <<= 8;
  332.     return (u | *p);
  333. }
  334.  
  335. void
  336. #ifdef __STDC__
  337. __putshort(register u_short s, register u_char *msgp)
  338. #else
  339. __putshort(s, msgp)
  340.     register u_short s;
  341.     register u_char *msgp;
  342. #endif
  343. {
  344.     msgp[1] = s;
  345.     msgp[0] = s >> 8;
  346. }
  347.  
  348. void
  349. __putlong(l, msgp)
  350.     register u_long l;
  351.     register u_char *msgp;
  352. {
  353.     msgp[3] = l;
  354.     msgp[2] = (l >>= 8);
  355.     msgp[1] = (l >>= 8);
  356.     msgp[0] = l >> 8;
  357. }
  358.   
  359.